package org.senseframework.support.open.api.validate;

import org.senseframework.support.open.api.annotation.Encrypt;
import org.senseframework.support.open.api.service.ApiDefinition;
import org.senseframework.support.open.api.service.BaseFiledValidate;
import org.senseframework.support.open.api.service.TokenGenerate;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.regex.Matcher;

/**
 * lanjian update
 */
public class Validate {

    private String name;
    private String message;
    private String regex;
    private Integer min;
    private Integer max;
    private ValidateType validateType;

    public Validate(String name, String message, String regex, ValidateType validateType) {
        this.name = name;
        this.message = message;
        this.regex = regex;
        this.validateType = validateType;
    }

    public Validate(String name, String message, ValidateType validateType) {
        this.name = name;
        this.message = message;
        this.validateType = validateType;
    }

    public Validate(String name, String message, Integer min, Integer max, ValidateType validateType) {
        this.name = name;
        this.message = message;
        this.min = min;
        this.max = max;
        this.validateType = validateType;
    }

    private static void regex(Map body, String[] name, String[] regex, String[] message) {
        if (name.length == regex.length && regex.length == message.length) {
            for (int i = 0; i < name.length; i++) {
                new Validate(name[i], message[i], regex[i], ValidateType.pattern).validate(body);
            }
        } else {
            throw new RuntimeException();
        }
    }

    private static void length(Map body, String[] name, int[] min, int[] max, String[] messages) {
        if (name.length == min.length && min.length == max.length) {
            for (int i = 0; i < name.length; i++) {
                if (messages.length > i) {
                    new Validate(name[i], messages[i], min[i], max[i], ValidateType.length).validate(body);
                } else {
                    new Validate(name[i], name[i] + " must be " + min[i] + " to " + max[i], min[i], max[i], ValidateType.length).validate(body);
                }

            }
        } else {
            throw new RuntimeException();
        }
    }

    private static void notNull(Map body, String[] name, String[] messages) {
        for (int i = 0; i < name.length; i++) {
            if (messages.length > i) {
                new Validate(name[i], messages[i], ValidateType.notNull).validate(body);
            } else {
                new Validate(name[i], name[i] + " is necessary", ValidateType.notNull).validate(body);
            }
        }
    }

    private static void ValidateRepeatCommit(Map body, String name, String service) {
//        String uid = String.valueOf(body.get(name));
//        String key = "repeat_commit_" + uid + "_" + service;
//        Object o = MemcachedHelper.get(key);
//        if (o != null) {
//            throw new ValidateException("repeat commit for " + service, ApiDefinition.REPEAT_COMMIT);
//        } else {
//            MemcachedHelper.set(key, 60, uid + "-" + service);
//        }
    }


    private static void validateBlacklist(Map body, String name) {
//        String sUid = String.valueOf(body.get(name));
//        Integer uid = Integer.valueOf(sUid);
//        long count = Mongo.buildMongo().eq("uid", uid).eq("status", Status.active).count(AiChangDBTable.BLACKLIST);
//        if (count > 0) {
//            throw new ValidateException("blacklist uid", ApiDefinition.BLACKLIST);
//        }
    }

//    public static void sensitive(Map body, String[] name, SensitiveWordFilter sensitiveWordFilter) {
//        for (String aName : name) {
//            String needValidate = String.valueOf(body.get(aName));
//            boolean flag = sensitiveWordFilter.isContaintSensitiveWord(needValidate, SensitiveWordFilter.maxMatchType);
//            if (flag) {
//                throw new ValidateException("你输入的内容有非法字符", ApiDefinition.SENSITIVE_KEYWORD_CODE);
//            }
//        }
//    }


    public static void goValidate(Class clazz, Map body, MultipartFile[] files, TokenGenerate tokenGenerate, BaseFiledValidate baseFiledValidate, boolean encrypt) {

//        if (clazz.isAnnotationPresent(SensitiveKeyword.class)) {
//            SensitiveKeyword sensitiveKeyword = (SensitiveKeyword) clazz.getAnnotation(SensitiveKeyword.class);
//            Validate.sensitive(body, sensitiveKeyword.name(), sensitiveWordFilter);
//        }

        if (clazz.isAnnotationPresent(Encrypt.class)) {
            if (!encrypt) {
                throw new ValidateException("this service need encrypt", ApiDefinition.FAIL_CODE);
            }
        }

        if (baseFiledValidate != null) {
            if (baseFiledValidate.fileds() != null && baseFiledValidate.fileds().length != 0) {
                Validate.notNull(body, baseFiledValidate.fileds(), new String[]{});
            }
        }


        if (clazz.isAnnotationPresent(FileInfo.class)) {
            if (files == null || files.length == 0) {
                throw new ValidateException("file not be null or 0", ApiDefinition.FAIL_CODE);
            }
        }
        if (clazz.isAnnotationPresent(TokenValidate.class)) {
            if (tokenGenerate == null) {
                throw new RuntimeException("tokenGenerate is null");
            }
            tokenGenerate.validate(body);
        }
        if (clazz.isAnnotationPresent(Pattern.class)) {
            Pattern pattern = (Pattern) clazz.getAnnotation(Pattern.class);
            Validate.regex(body, pattern.name(), pattern.regex(), pattern.message());
        }
        if (clazz.isAnnotationPresent(Length.class)) {
            Length length = (Length) clazz.getAnnotation(Length.class);
            Validate.length(body, length.name(), length.min(), length.max(), length.message());
        }
        if (clazz.isAnnotationPresent(NotNull.class)) {
            NotNull notNull = (NotNull) clazz.getAnnotation(NotNull.class);
            Validate.notNull(body, notNull.name(), notNull.message());
        }
        if (clazz.isAnnotationPresent(Blacklist.class)) {
            Blacklist blacklist = (Blacklist) clazz.getAnnotation(Blacklist.class);
            validateBlacklist(body, blacklist.name());
        }
        if (clazz.isAnnotationPresent(RepeatCommit.class)) {
            RepeatCommit repeatCommit = (RepeatCommit) clazz.getAnnotation(RepeatCommit.class);
            ValidateRepeatCommit(body, repeatCommit.name(), repeatCommit.service());
        }

    }


    public void validate(Map map) {
        switch (validateType) {
            case notNull:
                if (StringUtils.isEmpty(map.get(name))) {
                    throw new ValidateException(message, ApiDefinition.VALIDATE_NOT_NULL_CODE);
                }
                break;
            case pattern:
                try {
                    Object str = map.get(name);
                    if (!StringUtils.isEmpty(str)) {
                        java.util.regex.Pattern p = java.util.regex.Pattern.compile(regex);
                        Matcher m = p.matcher(String.valueOf(str));
                        if (!m.matches()) {
                            throw new ValidateException(message, ApiDefinition.VALIDATE_PATTERN_CODE);
                        }
                    }
                } catch (Exception ex) {
                    throw new ValidateException(message, ApiDefinition.VALIDATE_NOT_NULL_CODE);
                }
                break;
            case length:
                if (StringUtils.isEmpty(map.get(name))) {
                    throw new ValidateException(message, ApiDefinition.VALIDATE_NOT_NULL_CODE);
                }
                try {
                    int length = String.valueOf(map.get(name)).getBytes("gbk").length;
                    if (length < min || length > max) {
                        throw new ValidateException(message, ApiDefinition.VALIDATE_LENGTH_CODE);
                    }
                } catch (UnsupportedEncodingException ignored) {
                }
                break;
        }
    }


}
